/******************************************************************************
 * ldns_key.i: LDNS key class
 *
 * Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
 *                     Karel Slany    (slany AT fit.vutbr.cz)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the organization nor the names of its
 *       contributors may be used to endorse or promote products derived from this
 *       software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
%typemap(in,numinputs=0,noblock=1) (ldns_key **)
{
 ldns_key *$1_key;
 $1 = &$1_key;
}
          
/* result generation */
%typemap(argout,noblock=1) (ldns_key **)
{
  $result = SWIG_Python_AppendOutput($result, SWIG_NewPointerObj(SWIG_as_voidptr($1_key), SWIGTYPE_p_ldns_struct_key, SWIG_POINTER_OWN |  0 ));
}

%exception ldns_key_set_pubkey_owner(ldns_key *k, ldns_rdf *r)  %{ $action Py_INCREF(obj1); %}

%nodefaultctor ldns_struct_key; //no default constructor & destructor
%nodefaultdtor ldns_struct_key;

%delobject ldns_key_free;
%delobject ldns_key_deep_free;
%newobject ldns_key_list_pop_key;
%newobject ldns_key2rr;
%newobject ldns_key_new_frm_algorithm;
%newobject ldns_key_new_frm_fp;
%newobject ldns_key_new_frm_fp_l;
%newobject ldns_key_new_frm_engine;

%rename(ldns_key) ldns_struct_key;

#ifdef LDNS_DEBUG
%rename(__ldns_key_free) ldns_key_free;
%inline %{
void _ldns_key_free (ldns_key* k) {
   printf("******** LDNS_KEY free 0x%lX ************\n", (long unsigned int)k);
   ldns_key_deep_free(k);
}
%}
#else
%rename(_ldns_key_free) ldns_key_deep_free;
%rename(__ldns_key_free) ldns_key_free;
#endif

%feature("docstring") ldns_struct_key "Key class

This class can contains all types of keys that are used in DNSSEC. Mostly used to store private keys, since public keys can also be stored in a ldns_rr with type LDNS_RR_TYPE_DNSKEY. This class can also store some variables that influence the signatures generated by signing with this key, for instance the inception date.

**Usage**

 >>> import ldns
 >>> ldns.ldns_init_random(open(\"/dev/random\",\"rb\"), 512/8)
 >>> key = ldns.ldns_key.new_frm_algorithm(ldns.LDNS_SIGN_DSA, 512) #generate new DSA key
 >>> print key
 Private-key-format: v1.2
 Algorithm: 3 (DSA)
 Prime(p): XXXXXXXXHRQBGRflHZQriSAoLI2g+LGvZz8BlEesO+ZQg65wrFGs9IC441y/mn3nFnXfCdtX6zbN5bQuabPdlQ==
 Subprime(q): XXXXXdnWs/cWsGDglhEyZRLEVA8=
 Base(g): XXXXXXXqrd+dm2bcxDBdCsZRzkXQ22FxCk2ycnjgevr+s2HfA57BPk3xwqCrHUwuOBVg3Fvq4bpldrCe0sT6Og==
 Private_value(x): XXXXXcVubZF33pj04z4ZoETsQW1Y=
 Public_value(y): XXXXXX8t6zfOxJHoy57qteIw9sOZ/Zu0yFiPO083sPm11NlFx3b4m7TJ2k41gYicHXHLUQK1p0xXFToeZEkPGQ==
 >>> fw = open(\"key.priv\", \"wb\")
 >>> key.print_to_file(fw) #write priv key to file
"

%extend ldns_struct_key {
 
 %pythoncode %{
        def __init__(self):
            self.this = _ldns.ldns_key_new()
            if not self.this:
                raise Exception("Can't create instance of this class")
       
        __swig_destroy__ = _ldns._ldns_key_free

        def __str__(self):
            """converts the data to presentation format"""
            return _ldns.ldns_key2str(self)


        def key_to_rr(self):
            """converts a ldns_key to a public key rr
               
               :returns: (ldns_rr \*) ldns_rr representation of the key
            """
            return _ldns.ldns_key2rr(self)
            #parameters: const ldns_key *,
            #retvals: ldns_rr *

        def print_to_file(self, file):
            """print a private key to the file ouput
               
               :param file: output file pointer
            """
            _ldns.ldns_key_print(file, self)
            #parameters: FILE *, const ldns_key *,
            #retvals: 

        #LDNS_KEY_CONSTRUCTORS_#
        @staticmethod
        def new_frm_fp(file, raiseException=True):
            """Creates a new priv key based on the contents of the file pointed by fp. 
               
               :param file: a file object
               :param raiseException: if True, an exception occurs in case a key instance can't be created
               :returns: key instance or None. If the object can't be created and raiseException is True, an exception occurs.
            """
            status, key = _ldns.ldns_key_new_frm_fp(file)
            if status != LDNS_STATUS_OK:
                if (raiseException): raise Exception("Can't create key, error: %s (%d)" % (_ldns.ldns_get_errorstr_by_id(status),status))
                return None
            return key

        @staticmethod
        def new_frm_fp_l(file, raiseException=True):
            """Creates a new private key based on the contents of the file pointed by fp. 
               
               :param file: a file object
               :param raiseException: if True, an exception occurs in case a key instance can't be created
               :returns: 
                  * key - key instance or None. If an instance can't be created and raiseException is True, an exception occurs.

                  * line - the line number (for debugging)
            """
            status, key, line = _ldns.ldns_key_new_frm_fp_l(file)
            if status != LDNS_STATUS_OK:
                if (raiseException): raise Exception("Can't create key, error: %d" % status)
                return None
            return key, line

        @staticmethod
        def new_frm_algorithm(algorithm, size, raiseException=True):
            """Creates a new key based on the algorithm. 
               
               :param algorithm: the algorithm to use
               :param size: the number of bytes for the keysize
               :param raiseException: if True, an exception occurs in case a key instance can't be created
               :returns: key instance or None. If the object can't be created and raiseException is True, an exception occurs.

               **Algorithms**
                 LDNS_SIGN_RSAMD5, LDNS_SIGN_RSASHA1, LDNS_SIGN_DSA, LDNS_SIGN_RSASHA1_NSEC3, LDNS_SIGN_RSASHA256, LDNS_SIGN_RSASHA256_NSEC3, LDNS_SIGN_RSASHA512, LDNS_SIGN_RSASHA512_NSEC3, LDNS_SIGN_DSA_NSEC3, LDNS_SIGN_HMACMD5, LDNS_SIGN_HMACSHA1, LDNS_SIGN_HMACSHA256
            """
            key = _ldns.ldns_key_new_frm_algorithm(algorithm, size)
            if (not key) and (raiseException): raise Exception("Can't create key, error: %d" % status)
            return key
        #_LDNS_KEY_CONSTRUCTORS#

        #LDNS_KEY_METHODS_#
        def algorithm(self):
            """return the signing alg of the key
               
               :returns: (ldns_signing_algorithm) the algorithm
            """
            return _ldns.ldns_key_algorithm(self)
            #parameters: const ldns_key *,
            #retvals: ldns_signing_algorithm

        def dsa_key(self):
            """returns the (openssl) DSA struct contained in the key
               
               :returns: (DSA \*) 
            """
            return _ldns.ldns_key_dsa_key(self)
            #parameters: const ldns_key *,
            #retvals: DSA *

        def evp_key(self):
            """returns the (openssl) EVP struct contained in the key
               
               :returns: (EVP_PKEY \*) the RSA * structure in the key
            """
            return _ldns.ldns_key_evp_key(self)
            #parameters: const ldns_key *,
            #retvals: EVP_PKEY *

        def expiration(self):
            """return the key's expiration date
               
               :returns: (uint32_t) the experiration date
            """
            return _ldns.ldns_key_expiration(self)
            #parameters: const ldns_key *,
            #retvals: uint32_t

        def flags(self):
            """return the flag of the key
               
               :returns: (uint16_t) the flag
            """
            return _ldns.ldns_key_flags(self)
            #parameters: const ldns_key *,
            #retvals: uint16_t

        def hmac_key(self):
            """return the hmac key data
               
               :returns: (unsigned char \*) the hmac key data
            """
            return _ldns.ldns_key_hmac_key(self)
            #parameters: const ldns_key *,
            #retvals: unsigned char *

        def hmac_size(self):
            """return the hmac key size
               
               :returns: (size_t) the hmac key size
            """
            return _ldns.ldns_key_hmac_size(self)
            #parameters: const ldns_key *,
            #retvals: size_t

        def inception(self):
            """return the key's inception date
               
               :returns: (uint32_t) the inception date
            """
            return _ldns.ldns_key_inception(self)
            #parameters: const ldns_key *,
            #retvals: uint32_t

        def keytag(self):
            """return the keytag
               
               :returns: (uint16_t) the keytag
            """
            return _ldns.ldns_key_keytag(self)
            #parameters: const ldns_key *,
            #retvals: uint16_t

        def origttl(self):
            """return the original ttl of the key
               
               :returns: (uint32_t) the original ttl
            """
            return _ldns.ldns_key_origttl(self)
            #parameters: const ldns_key *,
            #retvals: uint32_t

        def pubkey_owner(self):
            """return the public key's owner
               
               :returns: (ldns_rdf \*) the owner
            """
            return _ldns.ldns_key_pubkey_owner(self)
            #parameters: const ldns_key *,
            #retvals: ldns_rdf *

        def rsa_key(self):
            """returns the (openssl) RSA struct contained in the key
               
               :returns: (RSA \*) the RSA * structure in the key
            """
            return _ldns.ldns_key_rsa_key(self)
            #parameters: const ldns_key *,
            #retvals: RSA *

        def set_algorithm(self,l):
            """Set the key's algorithm.
               
               :param l:
                   the algorithm
            """
            _ldns.ldns_key_set_algorithm(self,l)
            #parameters: ldns_key *,ldns_signing_algorithm,
            #retvals: 

        def set_dsa_key(self,d):
            """Set the key's dsa data.
               
               :param d:
                   the dsa data
            """
            _ldns.ldns_key_set_dsa_key(self,d)
            #parameters: ldns_key *,DSA *,
            #retvals: 

        def set_evp_key(self,e):
            """Set the key's evp key.
               
               :param e:
                   the evp key
            """
            _ldns.ldns_key_set_evp_key(self,e)
            #parameters: ldns_key *,EVP_PKEY *,
            #retvals: 

        def set_expiration(self,e):
            """Set the key's expiration date (seconds after epoch).
               
               :param e:
                   the expiration
            """
            _ldns.ldns_key_set_expiration(self,e)
            #parameters: ldns_key *,uint32_t,
            #retvals: 

        def set_flags(self,flags):
            """Set the key's flags.
               
               :param flags:
                   the flags
            """
            _ldns.ldns_key_set_flags(self,flags)
            #parameters: ldns_key *,uint16_t,
            #retvals: 

        def set_hmac_key(self,hmac):
            """Set the key's hmac data.
               
               :param hmac:
                   the raw key data
            """
            _ldns.ldns_key_set_hmac_key(self,hmac)
            #parameters: ldns_key *,unsigned char *,
            #retvals: 

        def set_hmac_size(self,hmac_size):
            """Set the key's hmac size.
               
               :param hmac_size:
                   the size of the hmac data
            """
            _ldns.ldns_key_set_hmac_size(self,hmac_size)
            #parameters: ldns_key *,size_t,
            #retvals: 

        def set_inception(self,i):
            """Set the key's inception date (seconds after epoch).
               
               :param i:
                   the inception
            """
            _ldns.ldns_key_set_inception(self,i)
            #parameters: ldns_key *,uint32_t,
            #retvals: 

        def set_keytag(self,tag):
            """Set the key's key tag.
               
               :param tag:
                   the keytag
            """
            _ldns.ldns_key_set_keytag(self,tag)
            #parameters: ldns_key *,uint16_t,
            #retvals: 

        def set_origttl(self,t):
            """Set the key's original ttl.
               
               :param t:
                   the ttl
            """
            _ldns.ldns_key_set_origttl(self,t)
            #parameters: ldns_key *,uint32_t,
            #retvals: 

        def set_pubkey_owner(self,r):
            """Set the key's pubkey owner.
               
               :param r:
                   the owner
            """
            _ldns.ldns_key_set_pubkey_owner(self,r)
            #parameters: ldns_key *,ldns_rdf *,
            #retvals: 

        def set_rsa_key(self,r):
            """Set the key's rsa data.
               
               :param r:
                   the rsa data
            """
            _ldns.ldns_key_set_rsa_key(self,r)
            #parameters: ldns_key *,RSA *,
            #retvals: 

        def set_use(self,v):
            """set the use flag
               
               :param v:
                   the boolean value to set the _use field to
            """
            _ldns.ldns_key_set_use(self,v)
            #parameters: ldns_key *,bool,
            #retvals: 

        def use(self):
            """return the use flag
               
               :returns: (bool) the boolean value of the _use field
            """
            return _ldns.ldns_key_use(self)
            #parameters: const ldns_key *,
            #retvals: bool
            #_LDNS_KEY_METHODS#
 %}
}

%nodefaultctor ldns_struct_key_list; //no default constructor & destructor
%nodefaultdtor ldns_struct_key_list;

%newobject ldns_key_list_new;
%newobject ldns_key_list_pop_key;
%delobject ldns_key_list_free;
%delobject ldns_key_list_push_key;

%rename(ldns_key_list) ldns_struct_key_list;

#ifdef LDNS_DEBUG
%rename(__ldns_key_list_free) ldns_key_list_free;
%inline %{
void _ldns_key_list_free (ldns_key_list* k) {
   printf("******** LDNS_KEY_LIST free 0x%lX ************\n", (long unsigned int)k);
   ldns_key_list_free(k);
}
%}
#else
%rename(_ldns_key_list_free) ldns_key_list_free;
#endif

%extend ldns_struct_key_list {
 
 %pythoncode %{
        def __init__(self):
            self.this = _ldns.ldns_key_list_new()
            if not self.this:
                raise Exception("Can't create class")
       
        __swig_destroy__ = _ldns._ldns_key_list_free

        def keys(self):
            """Key list iterator"""
            for i in range(0, self.key_count()):
                yield self.key(i)

        def __str__(self):
            i = 0
            s = ""
            for k in self.keys():
                i += 1
                s += "key %d:\n   %s\n" % (i, str(k).replace("\n","\n   "))
            return s

           #LDNS_KEY_LIST_METHODS_#
        def key(self,nr):
            """returns a pointer to the key in the list at the given position
               
               :param nr:
                   the position in the list
               :returns: (ldns_key \*) the key
            """
            return _ldns.ldns_key_list_key(self,nr)
            #parameters: const ldns_key_list *,size_t,
            #retvals: ldns_key *

        def key_count(self):
            """returns the number of keys in the key list
               
               :returns: (size_t) the numbers of keys in the list
            """
            return _ldns.ldns_key_list_key_count(self)
            #parameters: const ldns_key_list *,
            #retvals: size_t

        def pop_key(self):
            """pops the last rr from a keylist
               
               :returns: (ldns_key \*) NULL if nothing to pop. Otherwise the popped RR
            """
            return _ldns.ldns_key_list_pop_key(self)
            #parameters: ldns_key_list *,
            #retvals: ldns_key *

        def push_key(self,key):
            """pushes a key to a keylist
               
               :param key:
                   the key to push
               :returns: (bool) false on error, otherwise true
            """
            return _ldns.ldns_key_list_push_key(self,key)
            #parameters: ldns_key_list *,ldns_key *,
            #retvals: bool

        def set_key_count(self,count):
            """Set the keylist's key count to count.
               
               :param count:
                   the cuont
            """
            _ldns.ldns_key_list_set_key_count(self,count)
            #parameters: ldns_key_list *,size_t,
            #retvals: 

        def set_use(self,v):
            """Set the 'use' flag for all keys in the list.
               
               :param v:
                   The value to set the use flags to
            """
            _ldns.ldns_key_list_set_use(self,v)
            #parameters: ldns_key_list *,bool,
            #retvals: 

           #_LDNS_KEY_LIST_METHODS#
 %}
}

